package me.nibo.webframework.service.account;

import me.nibo.webframework.commons.VariableUtils;
import me.nibo.webframework.commons.enumeration.ResourceType;
import me.nibo.webframework.dao.ResourceDao;
import me.nibo.webframework.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 账户业务逻辑
 */
@Service
@Transactional
public class AccountService {

    @Autowired
    private ResourceDao resourceDao;

    @Autowired
    private UserDao userDao;


    /**
     * 获取所有资源
     *
     * @param ignore 忽略的资源id
     * @return 资源实体Map集合
     */
    public List<Map<String, Object>> getResources(long... ignore) {
        return resourceDao.getAll(ignore);
    }

    /**
     * 获取用户信息
     *
     * @param username 用户名
     * @return 用户实体Map
     */
    public Map<String, Object> getUserByUserName(String username) {
        return userDao.getUserByName(username);
    }

    /**
     * 获取用户资源
     *
     * @param userId 用户id
     * @return 资源实体Map集合
     */
    public List<Map<String, Object>> getUserResources(long userId) {
        return resourceDao.getUserResources(userId);
    }

    /**
     * 合并资源，要获取资源的父类通过 "parent" key 来获取，如果不存在 "parent" key 表示该资源 Map 为根节点，
     * 要获取资源的子类通过 "children" key 来获取
     *
     * @param resources 要合并的资源实体 Map 集合
     * @return 合并好的树形资源实体 Map 集合
     */
    public List<Map<String, Object>> mergeResources(List<Map<String, Object>> resources) {
        return mergeResources(resources, null);
    }

    /**
     * 合并资源，要获取资源的父类通过 "parent" key 来获取，如果不存在 "parent" key 表示该资源 Map 为根节点，
     * 要获取资源的子类通过 "children" key 来获取
     *
     * @param resources  要合并的资源实体 Map 集合
     * @param ignoreType 要忽略资源类型
     * @return 合并好的树形资源实体 Map 集合
     */
    public List<Map<String, Object>> mergeResources(List<Map<String, Object>> resources, ResourceType ignoreType) {

        List<Map<String, Object>> result = new ArrayList<>();

        for (Map<String, Object> entity : resources) {

            Long parentId = VariableUtils.cast(entity.get("fk_parent_id"), Long.class);
            Integer type = VariableUtils.cast(entity.get("type"), Integer.class);

            if (parentId == null && (ignoreType == null || !ignoreType.getValue().equals(type))) {
                recursionResource(entity, resources, ignoreType);
                result.add(entity);
            }

        }

        return result;
    }

    /**
     * 递归并合并资源到指定的父类
     *
     * @param parent     父类
     * @param resources  资源实体 Map 集合
     * @param ignoreType 要忽略不合并的资源类型
     */
    private void recursionResource(Map<String, Object> parent,
                                   List<Map<String, Object>> resources,
                                   ResourceType ignoreType) {

        parent.put("children", new ArrayList<>());

        for (Map<String, Object> entity : resources) {
            Long parentId = VariableUtils.cast(entity.get("fk_parent_id"), Long.class);

            if (parentId == null) {
                continue;
            }

            Integer type = VariableUtils.cast(entity.get("type"), Integer.class);
            Long id = VariableUtils.cast(parent.get("id"), Long.class);

            if ((ignoreType == null || !ignoreType.getValue().equals(type)) && parentId.equals(id)) {
                recursionResource(entity, resources, ignoreType);
                List<Map<String, Object>> children = VariableUtils.cast(parent.get("children"));
                if (children != null) {
                    entity.put("parent", parent);
                    children.add(entity);
                }
            }
        }
    }

}
